package goroutine

import (
	"math"
	"runtime"
	"time"
	"fmt"
)

func SumSlice(slice []int) (sum int) {
	for _, v := range slice {
		sum += v
	}
	return
}

func Sum(from int, to int) (sum int) {
	sum = 0
	for i := from; i <= to; i++ {
		sum += i
	}
	return
}

func SumByRoutine(from int, to int) (sum int) {

	var numRoutine int = runtime.NumCPU()

	var ch chan int = make(chan int, 1)
	t := time.Now()

	for i := 0; i < numRoutine; i++ {
		go rsum( to / numRoutine * i, to / numRoutine * (i +1) +1 , ch)
	}
	t2 := time.Now()
	fmt.Println("goroutine全部启动耗时 ", t2.Sub(t))

	// wait for all goroutines quit
	t3 := time.Now()
	for i := 0; i < numRoutine; i++ {
		sum += <-ch
	}
	t4 := time.Now()
	fmt.Println("等待goroutine全部结束耗时 ", t4.Sub(t3))
	fmt.Println("全部结束耗时 ", t4.Sub(t))

	return
}

func SumSliceByRoutine(slice []int) (sum int) {
	numRoutine := runtime.NumCPU()
	runtime.GOMAXPROCS(numRoutine*2)

	dataLength := len(slice)
	blockSize := int(math.Ceil(float64(dataLength) / float64(numRoutine)))

	var ch chan int = make(chan int, 1)

	for i := 0; i < numRoutine; i++ {
		bStart := i * blockSize
		bEnd := (i + 1) * blockSize
		if bEnd >= dataLength {
			bEnd = dataLength
		}
		go rSumSlice(slice[bStart:bEnd], ch)
	}

	// wait for all goroutines quit
	for i := 0; i < numRoutine; i++ {
		sum += <-ch
	}
	return
}

func rSumSlice(data []int, ch chan int) {
	var sum int = 0
	for _, v := range data {
		sum += v
	}
	ch <- sum
}

func rsum(from int, to int, ch chan int) {
	var sum int = 0
	for i := from; i < to; i++ {
		sum += i
	}
	ch <- sum
}
